package com.example.multithread.completablefuture;

import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StopWatch;

import java.util.List;
import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

/**
 * @ClassName CompletableFutureDemo2
 * @Description TODO
 * @Author leejiliang
 * @DateTime 2020/5/25 3:12 PM
 * @Version 1.0
 */
@Slf4j
public class CompletableFutureDemo2 {
	static Random random = new Random();
	public static void main(String[] arg) {
		//五个运动员列表
		List<Athlete> athletes = List.of(
				new Athlete("jacky"),
				new Athlete("lucy"),
				new Athlete("tony"),
				new Athlete("tom"),
				new Athlete("tom2"),
				new Athlete("tom3"),
				new Athlete("tom3"),
				new Athlete("tom3"),
				new Athlete("tom3"),
				new Athlete("tom3"),
				new Athlete("tom3"),
				new Athlete("tom3"),
				new Athlete("tom3"),
				new Athlete("tom3"),
				new Athlete("tom3"),
				new Athlete("tom3"),
				new Athlete("tom3"),
				new Athlete("tom3"),
				new Athlete("tom3"),
				new Athlete("tom3"),
				new Athlete("tom3"),
				new Athlete("tom3"),
				new Athlete("tom3"),
				new Athlete("tom3"),
				new Athlete("tom3"),
				new Athlete("tom3"),
				new Athlete("tom3"),
				new Athlete("perter"));
		StopWatch stopWatch = new StopWatch();
//		stopWatch.start("以同步的方式开始测试");
//		List<String> result = runSync(athletes);

//		stopWatch.start("以并行流的方式开始测试");
//		List<String> result = runAsyncWithParallel(athletes);

//		stopWatch.start("用 CompletableFuture的方式开始测试");
//		List<String> result = runAsyncWithCF(athletes);

		ExecutorService executorService = Executors.newFixedThreadPool(30);
		stopWatch.start("用自定义线程池的方式使用 CompletableFuture 开始测试");
		List<String> result = runAsyncWithExecutor(athletes, executorService);

		stopWatch.stop();
		log.info(stopWatch.getTotalTimeSeconds() + "s");
		log.info(stopWatch.prettyPrint());
		result.forEach(log::info);
	}

	static List<String> runSync(List<Athlete> athletes) {
		return athletes.stream().map(CompletableFutureDemo2::runTest).collect(Collectors.toList());
	}

	static List<String> runAsyncWithParallel(List<Athlete> athletes) {
		return athletes.parallelStream().map(CompletableFutureDemo2::runTest).collect(Collectors.toList());
	}

	static List<String> runAsyncWithCF(List<Athlete> athletes) {
		List<CompletableFuture<String>> completableFutures = athletes.stream().map(i -> CompletableFuture.supplyAsync(() -> runTest(i))).collect(Collectors.toList());
		return completableFutures.stream().map(CompletableFuture::join).collect(Collectors.toList());
	}

	static List<String> runAsyncWithExecutor(List<Athlete> athletes, Executor executor) {
		List<CompletableFuture<String>> completableFutures = athletes.stream().map(i -> CompletableFuture.supplyAsync(() -> runTest(i), executor)).collect(Collectors.toList());
		return completableFutures.stream().map(CompletableFuture::join).collect(Collectors.toList());
	}



	static String runTest(Athlete athlete) {
		delay();
		return "我是: " + athlete.getName() + "我的测试成绩是: " + random.nextInt(10) + "s";
	}

	static String runTestTwo(Athlete athlete) {
		delay();
		return "我是: " + athlete.getName() + "我的测试成绩是: " + random.nextInt(10) + "s";
	}

	static void delay() {
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}
